<slot></slot>
<script>
  import { virtualListStore } from './virtualListStore.js'
  import { throttle } from '../../_thirdparty/lodash/timers.js'
  import { isFullscreen, attachFullscreenListener, detachFullscreenListener } from '../../_utils/fullscreen.js'
  import { mark, stop } from '../../_utils/marks.js'
  import { doubleRAF } from '../../_utils/doubleRAF.js'
  import { observe } from 'svelte-extras'
  import {
    addScrollListener,
    removeScrollListener,
    getScrollContainer,
    getOffsetHeight
  } from '../../_utils/scrollContainer.js'
  import { registerResizeListener, unregisterResizeListener } from '../../_utils/resize.js'

  const SCROLL_EVENT_DELAY = 300

  export default {
    oncreate () {
      mark('onCreate VirtualListContainer')
      const {
        realm
      } = this.get()
      this.store.setCurrentRealm(realm)
      this.setupScroll()
      this.setupFullscreen()
      this.onResize = this.onResize.bind(this)
      const { scrollTop } = this.store.get()
      const scrollContainer = getScrollContainer()
      if (scrollTop > 0) {
        this.observe('allVisibleItemsHaveHeight', allVisibleItemsHaveHeight => {
          console.log('allVisibleItemsHaveHeight', allVisibleItemsHaveHeight)
          const { initializedScrollTop } = this.get()
          if (!initializedScrollTop && allVisibleItemsHaveHeight) {
            this.set({ initializedScrollTop: true })
            requestAnimationFrame(() => {
              mark('set scrollTop')
              console.log('forcing scroll top to ', scrollTop)
              scrollContainer.scrollTop = scrollTop
              stop('set scrollTop')
              doubleRAF(() => {
                console.log('initialized VirtualList (1)')
                this.fire('initialized')
              })
            })
          }
        })
      } else {
        this.fire('noNeedToScroll')
        this.observe('allVisibleItemsHaveHeight', allVisibleItemsHaveHeight => {
          if (allVisibleItemsHaveHeight) {
            console.log('initialized VirtualList (2)')
            this.fire('initialized')
          }
        })
        this.onResize()
      }
      registerResizeListener(this.onResize)
      stop('onCreate VirtualListContainer')
    },
    ondestroy () {
      this.teardownScroll()
      this.teardownFullscreen()
      this.store.setCurrentRealm(null)
      unregisterResizeListener(this.onResize)
    },
    store: () => virtualListStore,
    methods: {
      observe,
      setupScroll () {
        this.scrollListener = throttle(event => {
          const { fullscreen } = this.get()
          if (fullscreen) {
            return
          }
          this.onScroll()
        }, SCROLL_EVENT_DELAY, {
          leading: true,
          trailing: true
        })
        addScrollListener(this.scrollListener)
      },
      teardownScroll () {
        removeScrollListener(this.scrollListener)
      },
      setupFullscreen () {
        this.onFullscreenChange = this.onFullscreenChange.bind(this)
        attachFullscreenListener(this.onFullscreenChange)
      },
      teardownFullscreen () {
        detachFullscreenListener(this.onFullscreenChange)
      },
      onScroll () {
        const { scrollTop, scrollHeight } = getScrollContainer()

        doubleRAF(() => {
          mark('onScroll -> setForRealm()')
          this.store.setForRealm({ scrollTop, scrollHeight })
          stop('onScroll -> setForRealm()')
        })
      },
      onFullscreenChange () {
        mark('onFullscreenChange')
        console.log('is fullscreen? ', isFullscreen())
        this.set({ fullscreen: isFullscreen() })
        stop('onFullscreenChange')
      },
      onResize () {
        this.store.setForRealm({
          scrollHeight: getScrollContainer().scrollHeight,
          offsetHeight: getOffsetHeight()
        })
      }
    },
    computed: {
      // TODO: bug in svelte/store – the observer in oncreate() never get removed without this hack
      allVisibleItemsHaveHeight: ({ $allVisibleItemsHaveHeight }) => $allVisibleItemsHaveHeight
    }
  }
</script>
